package com.isaac.actm.domain.repository.jpa;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;

import org.springframework.orm.jpa.JpaTemplate;
import org.springframework.transaction.annotation.Transactional;

import com.isaac.actm.domain.repository.Repository;

public class JPAAbstractRepositoryImpl<T> implements Repository<T> {

	public Class<T> entityClass;

	public JpaTemplate jpaTemplate;

	@SuppressWarnings("unchecked")
	public JPAAbstractRepositoryImpl() {
		this.entityClass = (Class<T>) ((ParameterizedType) getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];
	}

	@Transactional
	public void save(T entity) {
		try {
			Long id = getId(entity);
			if (id == null) {
				jpaTemplate.persist(entity);
			} else {
				jpaTemplate.merge(entity);
			}

		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	@Transactional
	public void delete(T entity) {
		jpaTemplate.remove(entity);
		jpaTemplate.flush();
	}

	@Transactional
	public void delete(long id) {
		T reference = jpaTemplate.getReference(entityClass, id);
		jpaTemplate.remove(reference);
		jpaTemplate.flush();
	}

	public T find(long id) {
		return jpaTemplate.find(entityClass, id);
	}

	private Long getId(T entity) throws NoSuchMethodException,
			IllegalAccessException, InvocationTargetException {
		Method method = entity.getClass().getMethod("getId");
		Long id = (Long) method.invoke(entity);
		return id;
	}

	public JpaTemplate getJpaTemplate() {
		return jpaTemplate;
	}

	public void setJpaTemplate(JpaTemplate jpaTemplate) {
		this.jpaTemplate = jpaTemplate;
	}

}
